home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / util1 / yk211src.lha / Yak_2.11_Src / settings.c < prev    next >
C/C++ Source or Header  |  1995-11-22  |  27KB  |  926 lines

  1. #define __USE_SYSBASE
  2. #include <exec/types.h>
  3. #include <exec/memory.h>
  4. #include <dos/dos.h>
  5. #include <libraries/iffparse.h>
  6. #include <prefs/prefhdr.h>
  7. #include <proto/exec.h>
  8. #include <proto/dos.h>
  9. #include <proto/iffparse.h>
  10. #include <string.h>
  11.  
  12. #include "code.h"
  13. #include "yak.h"
  14. #include "Requesters.h"
  15. #include "handlers.h"
  16. #include "hotkey_types.h"
  17. #include "Settings.h"
  18.  
  19.  
  20. #define CATCOMP_NUMBERS
  21. #include "yak_locale_strings.h"
  22.  
  23. extern struct Library *IFFParseBase;
  24.  
  25. #if defined (PREFS) || defined (CONV)
  26. #  ifdef _DCC
  27. #    include <lists.h>
  28. #  else
  29. #    include "sas_lists.h"
  30. #  endif
  31. #  include "gui.h"
  32. #  include "Root_window.h"
  33. #  include "MouseCycling_window.h"
  34. #  include "Options_window.h"
  35. #  include "KeyDef_window.h"
  36. #  include "Blank_window.h"
  37. #  include "Misc_window.h"
  38. #  include "Hotkey_window.h"
  39.    static APTR WriteConfig(struct IFFHandle *iff, UBYTE *chunkbuf);
  40.    static APTR WriteHandlers(struct IFFHandle *iff, UBYTE *chunkbuf);
  41.    static APTR WriteHotkey(struct IFFHandle *iff, UBYTE *chunkbuf, YakHotKey *yhk);
  42. #else
  43. #  include "ClickDrive.h"
  44. #  include "BlackBorder.h"
  45. #  include "MMB_Shift.h"
  46. #  include "UnixDirs.h"
  47. #  include "FullWorkbench.h"
  48. #endif
  49.  
  50. #ifndef CONV
  51. static APTR ReadConfig(UBYTE *chunkbuf, ULONG size);
  52. static APTR ReadHandlers(UBYTE *chunkbuf, ULONG size);
  53. static APTR ReadHotkey(UBYTE *chunkbuf, ULONG size);
  54. #endif
  55.  
  56. #define ID_YKCF MAKE_ID('Y','K','C','F')
  57. #define ID_YKHD MAKE_ID('Y','K','H','D')
  58. #define ID_YKHK MAKE_ID('Y','K','H','K')
  59.  
  60. static UWORD PrefsVersionRead;
  61.  
  62. /*
  63.  * Used for compatibility
  64.  *
  65.  * +----------------+-------------+
  66.  * |YAKPREFSVERSION | Yak version |
  67.  * +----------------+-------------+
  68.  * | 0              | Yak 2.00    |
  69.  * | 1              | Yak 2.04    |
  70.  * +----------------+-------------+
  71.  */
  72.  
  73. #define YAKPREFSVERSION 1
  74.  
  75.  
  76.  
  77.  
  78. #define MAXBUFSIZE 1024
  79.  
  80.  
  81. #define DEF_AUTOPOINT_DELAY    2
  82. ULONG    autopoint_delay;           /* used for autopoint */
  83.  
  84. #define DEF_VOLUME            48
  85. ULONG    click_volume;              /* used for keyclick */
  86.  
  87. #define DEF_SCREENBLANKSECS        300
  88. ULONG    blanksecs; 
  89. ULONG    blanktimeout;
  90. ULONG    blankcount;                /* countdown to blank-time */
  91. ULONG    screenblank;               /* method used to blank screen */
  92.  
  93. #define DEF_MOUSEBLANKSECS         5
  94. ULONG    mouseblank;                /* method used to blank mouse */
  95. ULONG    mblanksecs;
  96. ULONG    mblanktimeout;
  97. ULONG    mblankcount;               /* countdown to mouse-blank-time */
  98.  
  99. static const BOOL DEF_TOGGLE[NUM_TOGGLES] = {
  100.         TRUE,         /* autopoint       */
  101.         FALSE,        /* keyactivate     */
  102.         FALSE,        /* autopop         */
  103.         FALSE,        /* rmbactivate     */
  104.         FALSE,        /* wildstar        */
  105.         TRUE,         /* scractivate     */
  106.         FALSE,        /* noclick         */
  107.         FALSE,        /* mmbactivate     */
  108.         FALSE,        /* blackborder     */
  109.         TRUE,         /* blankmouseonkey */
  110.         FALSE,        /* mmbshift        */
  111.         FALSE,        /* UnixDirs        */
  112.         FALSE,        /* SlashDir        */
  113.         FALSE,        /* fullworkbench   */
  114.         FALSE         /* CapShift        */
  115. };
  116.  
  117.  
  118.  
  119. #ifdef PREFS
  120.  
  121. #  define TOGGLE_DESCRIPTION(DefState, Gadget, WindowID) {(BOOL)DefState, (UWORD)Gadget, (UBYTE)WindowID}
  122.  
  123. #else   /* Yak commodity only */
  124.  
  125. #  define TOGGLE_DESCRIPTION(DefState, Gadget, WindowID) {(BOOL)DefState}
  126.  
  127. #endif
  128.  
  129. ToggleData toggles[] = {
  130.         TOGGLE_DESCRIPTION( TRUE, GDX_AutoCheck,          ROOT_WINDOW),
  131.         TOGGLE_DESCRIPTION(FALSE, GDX_KeyActCheck,        ROOT_WINDOW),
  132.         TOGGLE_DESCRIPTION(FALSE, GDX_AutoPopCheck,       ROOT_WINDOW),
  133.         TOGGLE_DESCRIPTION(FALSE, GDX_RMBActCheck,        ROOT_WINDOW),
  134.         TOGGLE_DESCRIPTION(FALSE, GDX_WildStarCheck,      MISC_WINDOW),
  135.         TOGGLE_DESCRIPTION( TRUE, GDX_ScrActCheck,        ROOT_WINDOW),
  136.         TOGGLE_DESCRIPTION(FALSE, GDX_NoClickCheck,       MISC_WINDOW),
  137.         TOGGLE_DESCRIPTION(FALSE, GDX_MMBActCheck,        ROOT_WINDOW),
  138.         TOGGLE_DESCRIPTION(FALSE, GDX_BlackBorderCheck,   MISC_WINDOW),
  139.         TOGGLE_DESCRIPTION( TRUE, GDX_BlankMouseOnKey,    BLANK_WINDOW),
  140.         TOGGLE_DESCRIPTION(FALSE, GDX_MMBShiftCheck,      MISC_WINDOW),
  141.         TOGGLE_DESCRIPTION(FALSE, GDX_UnixDirsCheck,      MISC_WINDOW),
  142.         TOGGLE_DESCRIPTION(FALSE, GDX_SlashDirCheck,      MISC_WINDOW),
  143.         TOGGLE_DESCRIPTION(FALSE, GDX_FullWorkbenchCheck, MISC_WINDOW),
  144.         TOGGLE_DESCRIPTION(FALSE, GDX_CapShiftCheck,      MISC_WINDOW)
  145. };
  146.  
  147.  
  148. static const char *DEF_PATTERN[NUM_PATTERNS] = {
  149.          "#?",               /* autoactivation screens */
  150.          "~(Workbench)"      /* autopop windows */
  151. };
  152.  
  153. PatternData patterns[NUM_PATTERNS] = {
  154.         { "#?", NULL },                 /* autoactivation screens */
  155.         { "~(Workbench)", NULL }        /* autopop windows */
  156. };
  157.  
  158.  
  159.  
  160.  
  161. /* Chunks to stop on */
  162. #define NUMSTOPS 3
  163. LONG stopchunks[] = {
  164.         ID_PREF, ID_YKCF,
  165.         ID_PREF, ID_YKHD,
  166.         ID_PREF, ID_YKHK
  167. };
  168.  
  169. struct PrefHeader PrefHdrChunk = {
  170.       YAKPREFSVERSION, 0, 0
  171. };
  172.  
  173.  
  174.  
  175. /* parse pattern, report errors */
  176. __regargs BOOL
  177. InitPattern(char *newpatstr, PatternData *pdata)
  178. {
  179.         char *patstr = newpatstr ? newpatstr : pdata->patstr;
  180.         char *pat;
  181.         LONG len;
  182.  
  183.         if (pat = AllocVec(len = strlen(patstr)*3+10, MEMF_CLEAR))
  184.         {
  185.                 if (ParsePattern(patstr, pat, len) != -1)
  186.                 {
  187.                         if (newpatstr) strncpy(pdata->patstr, newpatstr, PATLEN);
  188.                         if (pdata->pat) FreeVec(pdata->pat); 
  189.                         pdata->pat = pat;
  190.                         return TRUE;
  191.                 }
  192.                 
  193.                 PostError("%s:\n\"%s\"", getString(Parsing_Pattern_ERR), patstr);
  194.                 FreeVec(pat);
  195.         }
  196.         else PostError(getString(Allocation_ERR));
  197.         return FALSE;
  198. }
  199.  
  200.  
  201. /* Set default settings */
  202. void
  203. SetDefaultSettings(void)
  204. {
  205.     register UWORD   i;
  206.  
  207.     /* Config */
  208.     for (i=0; i < NUM_TOGGLES; i++)
  209.         toggles[i].pos = DEF_TOGGLE[i];
  210.  
  211.     for (i=0; i< NUM_PATTERNS; i++)
  212.         strcpy(patterns[i].patstr, DEF_PATTERN[i]);
  213.  
  214.     autopoint_delay = DEF_AUTOPOINT_DELAY;
  215.     click_volume    = DEF_VOLUME;
  216.     blanksecs       = DEF_SCREENBLANKSECS;
  217.     mblanksecs      = DEF_MOUSEBLANKSECS;
  218.     mouseblank      = MB_SPRITES;
  219.     screenblank     = SB_BLACKSCREEN;
  220.  
  221.     /* Hotkeys */
  222.     DeleteYakHotKeyList();
  223.  
  224.  
  225.     /* Mouse Cycling */
  226.     CleanMouseCycling();
  227.     for (i=0; i<NUM_HANDLERS; i++)
  228.     {
  229.         CopyMem((char *)&DEF_MOUSECYCLING[i], (char *)&MouseCyclingHandlers[i], (long)sizeof(YakHandler));
  230.         MouseCyclingHandlers[i].KeyDef = DupStr(MouseCyclingHandlers[i].KeyDef);
  231.     }
  232. }
  233.  
  234. #define WORD_ALIGN(ptr) ((ULONG)(ptr + 1) & ~1)
  235.  
  236. #ifndef CONV
  237.  
  238. /* Read Preferences */
  239. void
  240. LoadSettings(char *filename)
  241. {
  242.     struct IFFHandle *iff;
  243.     APTR              error = Opening_prefs_file_ERR; /* Temporarily */
  244.     BOOL              cont = TRUE;
  245.  
  246.     /* First: set default values */
  247.     SetDefaultSettings();
  248.  
  249.     /* Allocate IFF handle */
  250.     if (iff=AllocIFF())
  251.     {
  252.         /* Open IFF File */
  253.         if (iff->iff_Stream=Open(filename, MODE_OLDFILE))
  254.         {
  255.             /* Init IFF handle */
  256.             InitIFFasDOS(iff);
  257.  
  258.             /* Open IFF handle */
  259.             if (!OpenIFF(iff, IFFF_READ))
  260.             {
  261.                 /* Set IFF chunk types */
  262.                 if (!PropChunk(iff, ID_PREF, ID_PRHD) &&
  263.                     !StopChunks(iff, stopchunks, NUMSTOPS) &&
  264.                     !StopOnExit(iff, ID_PREF, ID_FORM) )
  265.                 {
  266.                     error = Invalid_prefs_file_ERR; /* Temporarily */
  267.  
  268.                     /* Start IFF parsing */
  269.                     if (!ParseIFF(iff, IFFPARSE_STEP))
  270.                     {
  271.                         struct ContextNode *cn;
  272.  
  273.                         /* Check IFF type */
  274.                         if ( (cn=CurrentChunk(iff)) &&
  275.                             (cn->cn_ID   == ID_FORM) &&
  276.                             (cn->cn_Type == ID_PREF) )
  277.                         {
  278.                             if (!ParseIFF(iff, IFFPARSE_SCAN))
  279.                             {
  280.                                 struct StoredProperty *sp;
  281.  
  282.                                 /* Get pointer to PRHD chunk */
  283.                                 if (sp=FindProp(iff, ID_PREF, ID_PRHD))
  284.                                 {
  285.                                     struct PrefHeader *ph=(struct PrefHeader *) sp->sp_Data;
  286.                             
  287.                                     PrefsVersionRead = ph->ph_Version;
  288.  
  289.                                     error = NULL; /* No error: temporarily */
  290.  
  291.                                     /* Parse IFF chunks */
  292.                                     do
  293.                                     {
  294.                                         APTR   localerr;
  295.                                         char   localstr[5];
  296.  
  297.                                         /* Get current chunk */
  298.                                         if (cn=CurrentChunk(iff))
  299.                                         {
  300.                                             UBYTE *chunkbuf;
  301.                                             ULONG  size=cn->cn_Size;
  302.  
  303.                                             /* Allocate memory for config buffer */
  304.                                             if (chunkbuf=AllocVec(size, 0L))
  305.                                             {
  306.                                                 /* Read chunk */
  307.                                                 if (ReadChunkBytes(iff, chunkbuf, size) == size)
  308.                                                 {
  309.                                                     switch(cn->cn_ID) 
  310.                                                     {
  311.                                                       case ID_YKCF:
  312.                                                         localerr = ReadConfig(chunkbuf, size);
  313.                                                         break;
  314.                                                       case ID_YKHK:
  315.                                                         localerr = ReadHotkey(chunkbuf, size);
  316.                                                         break;      
  317.                                                       case ID_YKHD:
  318.                                                         localerr = ReadHandlers(chunkbuf, size);
  319.                                                         break;
  320.                                                     }
  321.  
  322.                                                     if (localerr)
  323.                                                     {
  324.                                                         cont = (BOOL)GetOrders(getString(Continue_Abort_ORDERS),
  325.                                                                                getString(localerr),
  326.                                                                                IDtoStr(cn->cn_ID, localstr));
  327.                                                     }
  328.                                                 }
  329.                                                 else
  330.                                                 {
  331.                                                     PostError(getString(Reading_prefs_file_ERR));
  332.                                                     cont = FALSE;
  333.                                                 }
  334.  
  335.                                                 FreeVec(chunkbuf);
  336.                                             }
  337.                                             else
  338.                                             {
  339.                                                 PostError(getString(Allocation_ERR));
  340.                                                 cont = FALSE;
  341.                                             }
  342.                                         }
  343.                                         /* Next parse step */
  344.                                     } while ((!ParseIFF(iff, IFFPARSE_SCAN)) && cont);
  345.                                 }
  346.                             }
  347.                         }
  348.                     }
  349.                 }
  350.                 CloseIFF(iff);
  351.             }
  352.             Close(iff->iff_Stream);
  353.         }
  354.         FreeIFF(iff);
  355.     }
  356.     else
  357.         PostError(getString(Allocation_ERR));
  358.  
  359.     if (error)
  360.         PostError("%s\n\"%s\"", getString(error), filename);
  361. }
  362.  
  363.  
  364.  
  365.  
  366. /* YKCF chunk format
  367.  *
  368.  *      UWORD NUM_TOGGLES
  369.  *        BOOL toggles[]
  370.  *      UWORD click_volume
  371.  *      UWORD autopoint_delay
  372.  *      UWORD blanksecs
  373.  *      UWORD mblanksecs
  374.  *      UWORD mouseblank
  375.  *      UWORD screenblank 
  376.  *      UWORD NUM_PATTERNS
  377.  *        STRING patterns[]
  378.  */
  379. static APTR
  380. ReadConfig(UBYTE *chunkbuf, ULONG size)
  381. {
  382.     UWORD *puword=(UWORD *)chunkbuf;
  383.     BOOL  *pbool;
  384.     UBYTE *pstr;
  385.     UWORD   i, n;
  386.  
  387.     if ((n=*puword) > (UWORD)NUM_TOGGLES)
  388.     {
  389.         n = (UWORD) NUM_TOGGLES;
  390.     }
  391.     pbool = puword+1;
  392.     for (i = 0; i < n; i++)
  393.         toggles[i].pos = *pbool++;
  394.     puword = pbool;
  395.         
  396.     /* Miscellaneous */
  397.         
  398.     click_volume    = *puword++;
  399.     autopoint_delay = *puword++;
  400.     blanksecs       = *puword++;
  401.     mblanksecs      = *puword++;
  402.     mouseblank      = *puword++;
  403.     
  404.     if ((mblanksecs == 0) && (blankmouseonkey == FALSE))
  405.     {
  406.         mouseblank = MB_NONE;
  407.     }
  408.  
  409.     if (PrefsVersionRead > 0)
  410.     {
  411.         screenblank = *puword++;
  412.         if (blanksecs == 0)
  413.         {
  414.             screenblank = SB_NONE;
  415.         }
  416.     }
  417.  
  418.     if ((n=*puword++) <= NUM_PATTERNS)
  419.     {
  420.         pstr = (UBYTE *)puword;
  421.         for (i = 0; i < n; i++)
  422.         {
  423.             strncpy(patterns[i].patstr, pstr, PATLEN);
  424.             patterns[i].patstr[PATLEN] = '\0';
  425.             pstr += strlen(pstr)+1;
  426.         }
  427.  
  428.  
  429. #ifndef PREFS                   /* Yak */
  430.         /* set-up patterns */
  431.         for (i = 0; i < NUM_PATTERNS; i++)
  432.             InitPattern(NULL, &patterns[i]);
  433.  
  434.         if (wildstar)
  435.             WILDSTARON;
  436.         else
  437.             WILDSTAROFF;
  438.  
  439.         SetClickDrive(noclick);
  440.  
  441.         ToggleBlackBorder(blackborder);
  442.  
  443.         ToggleFullWorkbench(fullworkbench);
  444.  
  445.         ToggleUnixDirs(unixdirs);
  446.  
  447.         ToggleMMBShift(mmbshift);
  448.  
  449.         blankcount  = blanktimeout  = 10*blanksecs;
  450.         mblankcount = mblanktimeout = 10*mblanksecs;
  451. #endif
  452.  
  453.         if ((pstr-chunkbuf) == size)
  454.         { 
  455.             /* Reading Ok */
  456.             return 0L;
  457.         }
  458.  
  459.     }
  460.     return Reading_chunk_ERR;
  461. }
  462.  
  463.  
  464.  
  465. /* YKHK chunk format
  466.  *
  467.  *      UWORD  type
  468.  *      UWORD  state
  469.  *      STRING name
  470.  *      STRING keydef
  471.  *      UWORD  optsnum
  472.  *         UWORD flags
  473.  *         [ STRING argstr[] ]
  474.  *         [ LONG   argnum[] ]
  475.  *                .
  476.  *                .
  477.  *                .
  478.  *
  479.  */
  480. static APTR
  481. ReadHotkey(UBYTE *chunkbuf, ULONG size)
  482. {
  483.     register UWORD *puword=(UWORD *)chunkbuf;
  484.     register UBYTE *pstr;
  485.     void           *pvoid;
  486.     LONG           *plong;
  487.  
  488.     YakHotKey      *yhk;
  489.     UWORD           type;
  490.  
  491.     UWORD           ol, optsnum;
  492.     OptDescription *curdesc;
  493.  
  494.     if ((type=*puword++) < NUM_HOTKEY_TYPES)
  495.     {
  496.         if (yhk = NewYakHotKey(type))
  497.         {
  498.             yhk->yhk_State   = *puword++;         /* State */
  499.             pstr = (UBYTE *)puword;
  500.  
  501.             if (ModifyYHKName(yhk, pstr))         /* Name */
  502.             {
  503.                 pstr += strlen(pstr)+1;
  504.  
  505.                 /* Take care of non word aligned addresses for 68000 */
  506.                 puword = (UWORD *)WORD_ALIGN(pstr);
  507.  
  508.                 if (ModifyYHKKeyDef(yhk, pstr))   /* KeyDef */
  509.                 {
  510.                     pstr += strlen(pstr)+1;
  511.  
  512.                     /* Options */
  513.                     /* Take care of non word aligned addresses for 68000 */
  514.                     puword = (UWORD *)WORD_ALIGN(pstr);
  515.  
  516.                     optsnum = *puword++;
  517.                     pvoid   = (void *)puword;
  518.  
  519.                     for (ol=0; ol<optsnum; ol++)
  520.                     {
  521.                         UWORD as=0;   /* ArgStr number */
  522.                         UWORD an=0;   /* ArgNum number */
  523.  
  524.                         curdesc = yhktypes[yhk->yhk_Type].yhkt_OptsList[ol].Desc;
  525.  
  526.                         puword = (UWORD *)pvoid;
  527.                         yhk->yhk_Option[ol].Flags = *puword++;
  528.                         pvoid = (void *)puword;
  529.  
  530.                         while (curdesc->Type != NO_OPT)
  531.                         {
  532.                             switch(curdesc->Type)
  533.                             {
  534.                                 case STRING_OPT:
  535.                                     if (yhk->yhk_Option[ol].Flags & curdesc->LocalID)
  536.                                     {
  537.                                         pstr = (UBYTE *)pvoid;
  538.                                         yhk->yhk_Option[ol].ArgStr[as] = DupStr(pstr);
  539.                                         pstr += strlen(pstr)+1;
  540.  
  541.                                         /* Take care of non word aligned addresses for 68000 */
  542.                                         pvoid = (void *)WORD_ALIGN(pstr);
  543.                                     }
  544.                                     as++;
  545.                                     break;
  546.  
  547.                                 case INTEGER_OPT:
  548.                                     if (yhk->yhk_Option[ol].Flags & curdesc->LocalID)
  549.                                     {
  550.                                         plong = (LONG *)pvoid;
  551.                                         yhk->yhk_Option[ol].ArgNum[an] = *plong++;
  552.                                         pvoid = (void *)plong;
  553.                                     }
  554.                                     an++;
  555.                                     break;
  556.                             }
  557.  
  558.                             curdesc++;
  559.                         }
  560.                     }
  561.  
  562.                     if (((UBYTE *)pvoid-chunkbuf) == size)
  563.                         return 0L;  /* Reading Ok */
  564.  
  565.                 }
  566.  
  567.             }
  568.  
  569.             DeleteYakHotKey(yhk);
  570.         }
  571.  
  572.     }
  573.  
  574.     return Reading_chunk_ERR;
  575. }
  576.  
  577.  
  578. /* YKHD chunk format
  579.  *
  580.  *      UWORD NUM_HANDLERS
  581.  *        UWORD  handler[0].State
  582.  *        UWORD  handler[0].RequiredClicks
  583.  *        STRING handler[0].KeyDef
  584.  *        STRING handler[0].ScreenPatternStr
  585.  *               .
  586.  *               .
  587.  *               .
  588.  */
  589. static APTR
  590. ReadHandlers(UBYTE *chunkbuf, ULONG size)
  591. {
  592.     register UWORD *puword=(UWORD *)chunkbuf;
  593.     register UBYTE *pstr;
  594.  
  595.     register UWORD   i,n;
  596.  
  597.     if ((n=*puword++) <= NUM_HANDLERS)
  598.     {
  599.         for (i = 0; i < n; i++)
  600.         {
  601.             char *keydef;
  602.  
  603.             MouseCyclingHandlers[i].State = *puword++;
  604.             
  605.             MouseCyclingHandlers[i].RequiredClicks = *puword++;
  606.             
  607.             MouseCyclingHandlers[i].Options = *puword++;
  608.             
  609.             pstr = (UBYTE *)puword;
  610.  
  611.             keydef = DupStr(pstr);
  612.             if (MouseCyclingHandlers[i].KeyDef)
  613.                 FreeVec(MouseCyclingHandlers[i].KeyDef);
  614.             MouseCyclingHandlers[i].KeyDef = keydef;
  615.  
  616.             pstr += strlen(pstr)+1;
  617.             
  618.             strncpy(MouseCyclingHandlers[i].ScreenPatternData.patstr, pstr, PATLEN);
  619.  
  620.             pstr += strlen(pstr)+1;
  621.  
  622.             /* Take care of non word aligned addresses for 68000 */
  623.             puword = (UWORD *)WORD_ALIGN(pstr);
  624.  
  625.         }
  626.  
  627.         ToggleMouseCycling();
  628.  
  629.         if (((UBYTE *)puword-chunkbuf) == size)
  630.             return 0L;          /* Reading Ok */
  631.     }
  632.     return Reading_chunk_ERR;
  633. }
  634.  
  635.  
  636.  
  637. #endif
  638.  
  639. #if defined(PREFS) || defined(CONV)
  640.  
  641. /* Copy a file */
  642. #define COPYBUFSIZE 2048
  643. BOOL
  644. CopyFile(char *source, char *dest)
  645. {
  646.     BOOL  ret=FALSE;
  647.     char *copybuf;
  648.  
  649.     /* Allocate copy buffer */
  650.     if (copybuf= AllocMem(COPYBUFSIZE, 0))
  651.     {
  652.         BPTR infh;
  653.  
  654.         /* Open source file */
  655.         if (infh=Open(source, MODE_OLDFILE))
  656.         {
  657.             BPTR outfh;
  658.  
  659.             /* Open destination file */
  660.             if (outfh=Open(dest, MODE_NEWFILE))
  661.             {
  662.                 LONG n;
  663.  
  664.                 /* Copy file */
  665.                 while ((n=Read(infh, copybuf, COPYBUFSIZE)) > 0)
  666.                     if (Write(outfh, copybuf, n) != n) break;
  667.  
  668.                 /* No error? */
  669.                 if (!n) ret=TRUE;
  670.  
  671.                 Close(outfh);
  672.             }
  673.             Close(infh);
  674.         }
  675.         FreeMem(copybuf, COPYBUFSIZE);
  676.     }
  677.     else
  678.         PostError(getString(Allocation_ERR));
  679.  
  680.  
  681.     return ret;
  682. }
  683.  
  684.  
  685. /* Write Preferences */
  686. void
  687. SaveSettings(char *filename)
  688. {
  689.     UBYTE *chunkbuf;
  690.     APTR   error = Opening_prefs_file_ERR; /* Temporarily */
  691.  
  692.     /* Allocate memory for config buffer */
  693.     if (chunkbuf=AllocVec(MAXBUFSIZE, 0L))
  694.     {
  695.         struct IFFHandle *iff;
  696.  
  697.         /* Allocate IFF handle */
  698.         if (iff=AllocIFF())
  699.         {
  700.             /* Open IFF File */
  701.             if (iff->iff_Stream=Open(filename, MODE_NEWFILE))
  702.             {
  703.                 /* Init IFF handle */
  704.                 InitIFFasDOS(iff);
  705.  
  706.                 /* Open IFF handle */
  707.                 if (!OpenIFF(iff, IFFF_WRITE))
  708.                 {
  709.                     error = Writing_prefs_file_ERR; /* Temporarily */
  710.  
  711.                     /* Push FORM IFF chunk */
  712.                     if (!PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
  713.                     {
  714.                         /* Write PRHD IFF chunk */
  715.                         if (!PushChunk(iff, 0, ID_PRHD, sizeof(struct PrefHeader)) &&
  716.                             (WriteChunkBytes(iff, 
  717.                                              (UBYTE *) &PrefHdrChunk,
  718.                                              sizeof(struct PrefHeader)) == sizeof(struct PrefHeader)) &&
  719.                             !PopChunk(iff))
  720.                         {
  721.                             YakHotKey      *yhk;
  722.                             register UWORD  type;
  723.  
  724.                             error = WriteConfig(iff, chunkbuf);
  725.  
  726.                             if (!error) error = WriteHandlers(iff, chunkbuf);
  727.  
  728.                             for (type = 0; type < NUM_HOTKEY_TYPES && !error; type++)
  729.                                 for (yhk = (YakHotKey *)GetHead(keylist(type));
  730.                                      yhk && !error;
  731.                                      yhk = (YakHotKey *)GetSucc(yhk))
  732.                                 {
  733.                                     error = WriteHotkey(iff, chunkbuf, yhk);
  734.                                 }
  735.  
  736.                         }
  737.                         if (PopChunk(iff)) /* close out the FORM */
  738.                             error = Writing_prefs_file_ERR;
  739.                     }
  740.                     CloseIFF(iff);
  741.                 }
  742.                 Close(iff->iff_Stream);
  743.             }
  744.             FreeIFF(iff);
  745.         }
  746.         FreeVec(chunkbuf);
  747.     }
  748.     else
  749.         PostError(getString(Allocation_ERR));
  750.  
  751.     if (error)
  752.         PostError("%s\n\"%s\"", getString(error), filename);
  753. }
  754.  
  755.  
  756. static APTR
  757. WriteConfig(struct IFFHandle *iff, UBYTE *chunkbuf)
  758. {
  759.     register UWORD *puword=(UWORD *)chunkbuf;
  760.     register BOOL  *pbool;
  761.     register UBYTE *pstr;
  762.  
  763.     register UWORD i;
  764.     ULONG          size=0;
  765.  
  766.     /* toggles */
  767.     *puword++ =  (UWORD) NUM_TOGGLES;
  768.     pbool     = puword;
  769.     for (i = 0; i < NUM_TOGGLES; i++)
  770.             *pbool++ = toggles[i].pos;
  771.     puword    = pbool;
  772.  
  773.     /* miscellaneous */
  774.     *puword++ = click_volume;
  775.     *puword++ = autopoint_delay;
  776.     *puword++ = blanksecs;
  777.     *puword++ = mblanksecs;
  778.     *puword++ = mouseblank;
  779.     *puword++ = screenblank;
  780.  
  781.     /* patterns */
  782.     *puword++ = NUM_PATTERNS;
  783.     pstr      = (UBYTE *)puword;
  784.     for (i = 0; i < NUM_PATTERNS; i++)
  785.     {
  786.         strcpy(pstr, patterns[i].patstr);
  787.         pstr += strlen(pstr)+1;
  788.     }
  789.  
  790.     /* Write Chunk  */
  791.     size = pstr - chunkbuf;
  792.     if ((PushChunk(iff, 0, ID_YKCF, size)) ||
  793.         (WriteChunkBytes(iff, chunkbuf, size) != size) ||
  794.         (PopChunk(iff)))
  795.        return Writing_prefs_file_ERR;
  796.  
  797.     /* All OK. */
  798.     return NULL;
  799. }
  800.  
  801. static APTR
  802. WriteHotkey(struct IFFHandle *iff, UBYTE *chunkbuf, YakHotKey *yhk)
  803. {
  804.     UWORD          *puword=(UWORD *)chunkbuf;
  805.     UBYTE          *pstr;
  806.     void           *pvoid;
  807.     LONG           *plong;
  808.     UWORD           ol, optsnum;
  809.     OptDescription *curdesc;
  810.  
  811.     ULONG    size;
  812.  
  813.     *puword++  = yhk->yhk_Type;     /* Type  */
  814.     *puword++  = yhk->yhk_State;    /* State */
  815.     pstr = (UBYTE *)puword;
  816.  
  817.     strcpy(pstr, yhk->yhk_Name);   /* Name */
  818.     pstr += strlen(pstr)+1;
  819.  
  820.     /* Take care of non word aligned addresses for 68000 */
  821.     puword = (UWORD *)WORD_ALIGN(pstr);
  822.  
  823.     strcpy(pstr, yhk->yhk_KeyDef); /* KeyDef */
  824.     pstr += strlen(pstr)+1;
  825.  
  826.     /* Options */
  827.     /* Take care of non word aligned addresses for 68000 */
  828.     puword = (UWORD *)WORD_ALIGN(pstr);
  829.  
  830.     *puword++ = optsnum  = YHK_Takes_Opt(yhk);
  831.     pvoid = (void *)puword;
  832.  
  833.     for (ol=0; ol<optsnum; ol++)
  834.     {
  835.         UWORD as=0;   /* ArgStr number */
  836.         UWORD an=0;   /* ArgNum number */
  837.  
  838.         curdesc = yhktypes[yhk->yhk_Type].yhkt_OptsList[ol].Desc;
  839.  
  840.         puword = (UWORD *)pvoid;
  841.         *puword++ = yhk->yhk_Option[ol].Flags;
  842.         pvoid = (void *)puword;
  843.  
  844.         while (curdesc->Type != NO_OPT)
  845.         {
  846.             switch(curdesc->Type)
  847.             {
  848.                 case STRING_OPT:
  849.                     if (yhk->yhk_Option[ol].Flags & curdesc->LocalID)
  850.                     {
  851.                         pstr = (UBYTE *)pvoid;
  852.                         strcpy(pstr, yhk->yhk_Option[ol].ArgStr[as]);
  853.                         pstr += strlen(pstr)+1;
  854.  
  855.                         /* Take care of non word aligned addresses for 68000 */
  856.                         pvoid = (void *)WORD_ALIGN(pstr);
  857.                     }
  858.                     as++;
  859.                     break;
  860.  
  861.                 case INTEGER_OPT:
  862.                     if (yhk->yhk_Option[ol].Flags & curdesc->LocalID)
  863.                     {
  864.                         plong = (LONG *)pvoid;
  865.                         *plong++ =yhk->yhk_Option[ol].ArgNum[an];
  866.                         pvoid = (void *)plong;
  867.                     }
  868.                     an++;
  869.                     break;
  870.             }
  871.  
  872.             curdesc++;
  873.         }
  874.     }
  875.  
  876.  
  877.     /* Write Chunk */
  878.     size = (UBYTE *)pvoid - chunkbuf;
  879.     if ((PushChunk(iff, 0, ID_YKHK, size)) ||
  880.         (WriteChunkBytes(iff, chunkbuf, size) != size) ||
  881.         (PopChunk(iff)))
  882.        return Writing_prefs_file_ERR;
  883.  
  884.     /* All OK. */
  885.     return 0L;
  886. }
  887.  
  888. static APTR
  889. WriteHandlers(struct IFFHandle *iff, UBYTE *chunkbuf)
  890. {
  891.     UWORD  *puword=(UWORD *)chunkbuf;
  892.     UBYTE  *pstr;
  893.     register UWORD i;
  894.  
  895.     ULONG    size;
  896.  
  897.     *puword++  = NUM_HANDLERS;
  898.     
  899.     for (i=0; i< NUM_HANDLERS; i++)
  900.     {
  901.         *puword++ = MouseCyclingHandlers[i].State;
  902.         *puword++ = MouseCyclingHandlers[i].RequiredClicks;
  903.         *puword++ = MouseCyclingHandlers[i].Options;
  904.         pstr = (UBYTE *)puword;
  905.         strcpy(pstr, MouseCyclingHandlers[i].KeyDef);
  906.         pstr += strlen(pstr)+1;
  907.         strcpy(pstr, MouseCyclingHandlers[i].ScreenPatternData.patstr);
  908.         pstr += strlen(pstr)+1;
  909.  
  910.         /* Take care of non word aligned addresses for 68000 */
  911.         puword = (UWORD *)WORD_ALIGN(pstr);
  912.     }
  913.  
  914.     /* Write Chunk */
  915.     size = (UBYTE *)puword - chunkbuf;
  916.     if ((PushChunk(iff, 0, ID_YKHD, size)) ||
  917.         (WriteChunkBytes(iff, chunkbuf, size) != size) ||
  918.         (PopChunk(iff)))
  919.        return Writing_prefs_file_ERR;
  920.  
  921.     /* All OK. */
  922.     return NULL;
  923. }
  924.  
  925. #endif
  926.